package com.feiyue.learning.guava;

import com.google.common.util.concurrent.*;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class GuavaDemo {
    public static final int SLEEP_GAP = 500;

    public static void main(String[] args) {
        MainJob mainJob = new MainJob();
        Thread mainThread = new Thread(mainJob);
        mainThread.setName("主线程");
        mainThread.start();

        Callable<Boolean> hotJob = new HotWaterJob();
        Callable<Boolean> washJob = new WashJob();

        // 创建 Java 线程池
        ExecutorService jpool = Executors.newFixedThreadPool(10);

        // 包装 Java 线程池，构建 Guava 线程池
        ListeningExecutorService gpool = MoreExecutors.listeningDecorator(jpool);

        // 使用 gPool 线程池异步执行 `热水` 和 `清洗` 工作, 通过 submit 方法提交任务，返回异步任务实例
        ListenableFuture<Boolean> hotFuture = gpool.submit(hotJob);

        // 绑定异步任务与回调实例
        Futures.addCallback(hotFuture, new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean r) {
                if (r) {
                    mainJob.waterOk = true;
                }
            }

            @Override
            public void onFailure(Throwable throwable) {
                System.out.println("烧水失败");
            }
        });

        ListenableFuture<Boolean> washFuture = gpool.submit(washJob);
        Futures.addCallback(washFuture, new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean r) {
                if (r) {
                    mainJob.cupOk = true;
                }
            }

            @Override
            public void onFailure(Throwable throwable) {
                System.out.println("杯子洗不了");
            }
        });
    }

    public static String getCurThreadName() {
        return Thread.currentThread().getName();
    }


    static class MainJob implements Runnable {
        int gap = SLEEP_GAP / 10;
        boolean waterOk = false;
        boolean cupOk = false;

        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(gap);
                    System.out.println("读书中...");
                } catch (InterruptedException e) {
                    System.out.println(getCurThreadName() + "发生异常");
                }
                if (waterOk && cupOk) {
                    drinkTea(waterOk, cupOk);
                }
            }
        }

        private void drinkTea(Boolean waterOk, Boolean cupOk) {
            if (waterOk && cupOk) {
                System.out.println("泡茶喝，茶喝完");
                this.waterOk = false;
                this.gap = SLEEP_GAP * 100;
            } else if (!waterOk) {
                System.out.println("水没烧开");
            } else if (!cupOk) {
                System.out.println("杯子没洗好");
            }
        }
    }

    static class HotWaterJob implements Callable<Boolean> {

        @Override
        public Boolean call() throws Exception {
            try {
                System.out.println("洗好水壶");
                System.out.println("灌入凉水");
                System.out.println("放在火上");
                Thread.sleep(SLEEP_GAP);
                System.out.println("水开了");
            } catch (InterruptedException e) {
                System.out.println("烧水发生异常");
                return false;
            }
            System.out.println("烧水结束");
            return true;
        }
    }

    static class WashJob implements Callable<Boolean> {

        @Override
        public Boolean call() throws Exception {
            try {
                System.out.println("洗茶壶");
                System.out.println("洗茶杯");
                System.out.println("拿茶叶");
                Thread.sleep(SLEEP_GAP);
                System.out.println("洗完了");
            } catch (InterruptedException e) {
                System.out.println("清洗工作发生异常");
                return false;
            }
            System.out.println("清洗工作结束");
            return true;
        }
    }
}
